#include "oj_control.hpp"
#include "../commen/httplib.h"
#include "../commen/log.hpp"
#include <memory>
#include <iostream>
#include <nlohmann/json.hpp>
#include "server/auth_handler.hpp"
#include "server/auth_middleware.hpp"

using namespace ns_oj_control;
using namespace ns_log;
using json = nlohmann::json;
using std::to_string;

OjControl *ctl_ptr = nullptr;

void Usage(const char *programName)
{
    std::cout << "Wrong usage!" << std::endl;
    std::cout << "Correct usage: " << programName << " port" << std::endl;
}

void AllQuestions([[maybe_unused]] const httplib::Request &req, httplib::Response &resp)
{
    std::string question_list;
    LogMessage(Debug, "题库请求到来\n");
    if (!ctl_ptr->AllQuestions(&question_list))
    {
        resp.status = 404;
        resp.set_content("{\"error\": \"Failed to get questions\"}", "application/json");
    }
    else
    {
        resp.status = 200;
        resp.set_content(question_list, "application/json;charset=utf-8");
    }
    LogMessage(Debug, "题库请求完毕\n");
}

void OneQuestion(const httplib::Request &req, httplib::Response &resp)
{
    LogMessage(Debug, "题目请求到来\n");
    std::string question_info;
    std::string number = req.matches[1];
    LogMessage(Debug, "题目请求到来, number: %s\n", number.c_str());
    if (!ctl_ptr->Question(number, &question_info))
    {
        resp.status = 404;
        resp.set_content("{\"error\": \"Question not found\"}", "application/json");
    }
    else
    {
        resp.status = 200;
        resp.set_content(question_info, "application/json;charset=utf-8");
    }
    LogMessage(Debug, "题目请求结束, number: %s\n", number.c_str());
}

void Judge(const httplib::Request &req, httplib::Response &resp)
{
    std::string in_json = req.body;
    std::string number = req.matches[1];
    LogMessage(Debug, "Judge 请求到来, number: %s\n, in_json: %s\n", number.c_str(), in_json.c_str());
    
    try {
        std::string out_json;
        std::string submit_time = std::to_string(std::time(nullptr));
        ctl_ptr->Judge(number, in_json, submit_time, &out_json);
        resp.status = 200;
        resp.set_content(out_json, "application/json;charset=utf-8");
    }
    catch (const std::exception& e) {
        LogMessage(Error, "Judge failed: %s\n", e.what());
        resp.status = 500;
        resp.set_content("{\"error\": \"Judge failed\"}", "application/json");
    }
}

void AddQuestion(const httplib::Request &req, httplib::Response &resp)
{
    LogMessage(Debug, "管理员添加题目\n");
    std::string in_json = req.body;
    LogMessage(Debug, "AddQuestion 请求到来, in_json: %s\n", in_json.c_str());
    if (!ctl_ptr->AddQuestion(in_json))
    {
        resp.status = 500;
        resp.set_content("{\"error\": \"添加题目失败\"}", "application/json;charset=utf-8");
    }
    else
    {
        resp.status = 200;
        resp.set_content("{\"message\": \"添加题目成功\"}", "application/json;charset=utf-8");
    }
}

void DeleteQuestion(const httplib::Request &req, httplib::Response &resp)
{
    LogMessage(Debug, "管理员删除题目\n");
    std::string number = req.matches[1];
    LogMessage(Debug, "DeleteQuestion 请求到来, number: %s\n", number.c_str());
    if (!ctl_ptr->DeleteQuestion(number))
    {
        resp.status = 500;
        resp.set_content("{\"error\": \"删除题目失败\"}", "application/json;charset=utf-8");
    }
    else
    {
        resp.status = 200;
        resp.set_content("{\"message\": \"删除题目成功\"}", "application/json;charset=utf-8");
    }
}

void GetSubmitRecords(const httplib::Request &req, httplib::Response &resp)
{
    LogMessage(Debug, "收到获取提交记录请求\n");

    try
    {
        if (!req.has_param("uid"))
        {
            LogMessage(Warning, "缺少uid参数\n");
            resp.status = 400;
            resp.set_content("{\"error\": \"Missing uid parameter\"}", "application/json");
            return;
        }

        int64_t uid = std::stoll(req.get_param_value("uid"));
        int number = std::stoi(req.matches[1].str());
        std::string out_json;
        if (ctl_ptr->GetSubmitRecords(uid, number, &out_json))
        {
            resp.status = 200;
            resp.set_content(out_json, "application/json");
            LogMessage(Info, "获取提交记录成功\n");
        }
        else
        {
            resp.status = 500;
            resp.set_content("{\"error\": \"Failed to get submit records\"}", "application/json");
            LogMessage(Error, "获取提交记录失败\n");
        }
    }
    catch (const std::exception &e)
    {
        LogMessage(Error, "处理请求异常: %s\n", e.what());
        resp.status = 500;
        resp.set_content("{\"error\": \"Internal server error\"}", "application/json");
    }
}

void CreateQuestionList(const httplib::Request &req, httplib::Response &resp)
{
    LogMessage(Debug, "收到创建题单请求\n");
    try
    {
        auto j = json::parse(req.body);
        if (!j.contains("uid") || !j.contains("title") || !j.contains("description") || !j.contains("is_public"))
        {
            LogMessage(Warning, "请求参数不完整\n");
            resp.status = 400;
            resp.set_content("{\"error\": \"Missing required fields\"}", "application/json");
            return;
        }

        int64_t uid = j["uid"].get<int64_t>();
        std::string title = j["title"].get<std::string>();
        std::string description = j["description"].get<std::string>();
        bool is_public = j["is_public"].get<bool>();
        std::string created_at = std::to_string(std::time(nullptr));
        std::string updated_at = created_at;
        std::string out_json;
        if (ctl_ptr->CreateQuestionList(uid, title, description, is_public, created_at, updated_at, &out_json))
        {
            resp.status = 200;
            resp.set_content(out_json, "application/json");
            LogMessage(Info, "创建题单成功\n");
        }
        else
        {
            resp.status = 500;
            resp.set_content("{\"error\": \"Failed to create question list\"}", "application/json");
            LogMessage(Error, "创建题单失败\n");
        }
    }
    catch (const json::exception &e)
    {
        LogMessage(Error, "JSON解析错误: %s\n", e.what());
        resp.status = 400;
        resp.set_content("{\"error\": \"Invalid JSON format\"}", "application/json");
    }
    catch (const std::exception &e)
    {
        LogMessage(Error, "处理请求异常: %s\n", e.what());
        resp.status = 500;
        resp.set_content("{\"error\": \"Internal server error\"}", "application/json");
    }
}

void AddToQuestionList(const httplib::Request &req, httplib::Response &resp)
{
    LogMessage(Debug, "收到添加题目到题单请求\n");

    try
    {
        auto j = json::parse(req.body);

        if (!j.contains("uid") || !j.contains("list_id") || !j.contains("number"))
        {
            LogMessage(Warning, "请求参数不完整\n");
            resp.status = 400;
            resp.set_content("{\"error\": \"Missing required fields\"}", "application/json");
            return;
        }

        int64_t uid = j["uid"].get<int64_t>();
        int64_t list_id = j["list_id"].get<int64_t>();
        int number = j["number"].get<int>();

        LogMessage(Debug, "参数解析完成: uid=%ld, list_id=%ld, number=%d\n",
                   uid, list_id, number);
        std::string updated_at = std::to_string(std::time(nullptr));
        
        if (ctl_ptr->AddToQuestionList(uid, list_id, number, updated_at))
        {
            resp.status = 200;
            resp.set_content("{\"status\": \"success\"}", "application/json");
            LogMessage(Info, "添加题目到题单成功\n");
        }
        else
        {
            resp.status = 500;
            resp.set_content("{\"error\": \"Failed to add question to list\"}", "application/json");
            LogMessage(Error, "添加题目到题单失败\n");
        }
    }
    catch (const json::exception &e)
    {
        LogMessage(Error, "JSON解析错误: %s\n", e.what());
        resp.status = 400;
        resp.set_content("{\"error\": \"Invalid JSON format\"}", "application/json");
    }
    catch (const std::exception &e)
    {
        LogMessage(Error, "处理请求异常: %s\n", e.what());
        resp.status = 500;
        resp.set_content("{\"error\": \"Internal server error\"}", "application/json");
    }
}

void GetQuestionList(const httplib::Request &req, httplib::Response &resp)
{
    LogMessage(Debug, "收到获取题单请求\n");

    try
    {
        if (!req.has_param("uid"))
        {
            LogMessage(Warning, "缺少必要参数\n");
            resp.status = 400;
            resp.set_content("{\"error\": \"Missing required parameters\"}", "application/json");
            return;
        }

        int64_t uid = std::stoll(req.get_param_value("uid"));

        std::string out_json;
        if (ctl_ptr->GetQuestionList(uid, &out_json))
        {
            resp.status = 200;
            resp.set_content(out_json, "application/json");
            LogMessage(Info, "获取题单成功\n");
        }
        else
        {
            resp.status = 500;
            resp.set_content("{\"error\": \"Failed to get question list\"}", "application/json");
            LogMessage(Error, "获取题单失败\n");
        }
    }
    catch (const std::exception &e)
    {
        LogMessage(Error, "处理请求异常: %s\n", e.what());
        resp.status = 500;
        resp.set_content("{\"error\": \"Internal server error\"}", "application/json");
    }
}

void RemoveFromQuestionList(const httplib::Request &req, httplib::Response &resp)
{
    LogMessage(Debug, "收到从题单删除题目请求\n");

    try
    {
        auto j = json::parse(req.body);

        if (!j.contains("uid") || !j.contains("list_id") || !j.contains("number"))
        {
            LogMessage(Warning, "请求参数不完整\n");
            resp.status = 400;
            resp.set_content("{\"error\": \"Missing required fields\"}", "application/json");
            return;
        }

        int64_t uid = j["uid"].get<int64_t>();
        int64_t list_id = j["list_id"].get<int64_t>();
        int number = j["number"].get<int>();

        LogMessage(Debug, "参数解析完成: uid=%ld, list_id=%ld, number=%d\n",
                   uid, list_id, number);

        if (ctl_ptr->RemoveFromQuestionList(uid, list_id, number))
        {
            resp.status = 200;
            resp.set_content("{\"status\": \"success\"}", "application/json");
            LogMessage(Info, "从题单删除题目成功\n");
        }
        else
        {
            resp.status = 500;
            resp.set_content("{\"error\": \"Failed to remove question from list\"}", "application/json");
            LogMessage(Error, "从题单删除题目失败\n");
        }
    }
    catch (const json::exception &e)
    {
        LogMessage(Error, "JSON解析错误: %s\n", e.what());
        resp.status = 400;
        resp.set_content("{\"error\": \"Invalid JSON format\"}", "application/json");
    }
    catch (const std::exception &e)
    {
        LogMessage(Error, "处理请求异常: %s\n", e.what());
        resp.status = 500;
        resp.set_content("{\"error\": \"Internal server error\"}", "application/json");
    }
}

void Login(const httplib::Request &req, httplib::Response &resp)
{
    LogMessage(Info, "用户进行登录操作\n");
    try
    {
        std::string username, password, sessionId;
        if (req.has_header("Cookie"))
        {
            sessionId = StringUtil::getHTTPHeaderValue("Cookie", "sessionId=", ";").second;
        }

        auto j = json::parse(req.body);
        if (j.contains("username"))
        {
            username = j["username"].get<std::string>();
        }
        if (j.contains("password"))
        {
            password = j["password"].get<std::string>();
        }

        LogMessage(Debug, "username: %s, password: %s, sessionId: %s\n",
                   username.c_str(), password.c_str(), sessionId.c_str());

        if (ctl_ptr->Login(username, password, sessionId))
        {
            if (!sessionId.empty())
                resp.set_header("Set-Cookie", "sessionId=" + sessionId + ";");
            resp.status = 200;
            resp.set_content("{\"status\": \"success\", \"message\": \"登录成功\"}",
                             "application/json");
            LogMessage(Info, "用户登录成功\n");
        }
        else
        {
            resp.status = 401;
            resp.set_content("{\"status\": \"error\", \"message\": \"登录失败\"}",
                             "application/json");
            LogMessage(Info, "用户登录失败\n");
        }
    }
    catch (const json::exception &e)
    {
        LogMessage(Error, "JSON解析错误: %s\n", e.what());
        resp.status = 400;
        resp.set_content("{\"error\": \"Invalid JSON format\"}", "application/json");
    }
    catch (const std::exception &e)
    {
        LogMessage(Error, "处理登录请求异常: %s\n", e.what());
        resp.status = 500;
        resp.set_content("{\"error\": \"Internal server error\"}", "application/json");
    }
}

void Register(const httplib::Request &req, httplib::Response &resp)
{
    LogMessage(Debug, "用户进行注册操作\n");
    try
    {
        auto j = json::parse(req.body);
        if (!j.contains("username") || !j.contains("password"))
        {
            LogMessage(Debug, "账号或密码字段不存在\n");
            resp.status = 400;
            resp.set_content("{\"status\": \"error\", \"message\": \"缺少必要字段\"}",
                             "application/json");
            return;
        }

        std::string username = j["username"].get<std::string>();
        std::string password = j["password"].get<std::string>();

        if (username.empty() || password.empty())
        {
            LogMessage(Debug, "账号或密码为空\n");
            resp.status = 400;
            resp.set_content("{\"status\": \"error\", \"message\": \"账号或密码不能为空\"}",
                             "application/json");
            return;
        }

        if (ctl_ptr->Register(username, password))
        {
            LogMessage(Debug, "注册成功\n");
            resp.status = 200;
            resp.set_content("{\"status\": \"success\", \"message\": \"注册成功\"}",
                             "application/json");
        }
        else
        {
            LogMessage(Debug, "注册失败\n");
            resp.status = 400;
            resp.set_content("{\"status\": \"error\", \"message\": \"注册失败\"}",
                             "application/json");
        }
    }
    catch (const json::exception &e)
    {
        LogMessage(Error, "JSON解析错误: %s\n", e.what());
        resp.status = 400;
        resp.set_content("{\"error\": \"Invalid JSON format\"}", "application/json");
    }
    catch (const std::exception &e)
    {
        LogMessage(Error, "处理注册请求异常: %s\n", e.what());
        resp.status = 500;
        resp.set_content("{\"error\": \"Internal server error\"}", "application/json");
    }
}

void Recovery([[maybe_unused]] int signo)
{
    ctl_ptr->RecoveryMachines();
}

const uint16_t PORT = 8888;

int main()
{
    lg.Clear();
    conf.SetLogStyle(Screen);
    httplib::Server svr;
    ctl_ptr = OjControl::GetInstance(); 

    auto auth_handler = std::make_shared<AuthHandler>(ctl_ptr->GetDBConn());
    signal(SIGINT, Recovery);

    // 基础路由
    svr.Get("/all_questions", AllQuestions);      // 获取所有题目
    svr.Get("/one_question/(\\d+)", OneQuestion); // 获取单个题目
    svr.Post("/judge/(\\d+)", Judge);             // 判题
    svr.Post("/add_question", AddQuestion);       // 添加题目
    svr.Delete("/question/(\\d+)", DeleteQuestion); // 删除题目

    // 认证相关路由
    svr.Post("/auth/login", [&auth_handler](const httplib::Request &req, httplib::Response &res)
             { auth_handler->handleLogin(req, res); }); // 登录

    svr.Post("/auth/register", [&auth_handler](const httplib::Request &req, httplib::Response &res)
             { auth_handler->handleRegister(req, res); }); // 注册

    // 提交记录相关路由
    svr.Get("/submit/list/(\\d+)", GetSubmitRecords); // 获取提交记录

    // 题单相关路由
    svr.Post("/question_list/create", CreateQuestionList);     // 创建题单
    svr.Post("/question_list/add", AddToQuestionList);         // 添加题目到题单
    svr.Get("/question_list/get", GetQuestionList);            // 获取题单
    svr.Post("/question_list/remove", RemoveFromQuestionList); // 从题单中删除题目

    // 设置静态文件目录 
    svr.set_base_dir("./web");

    // 启动服务器
    LogMessage(Info, "Server starting on port %d...\n", PORT);
    svr.listen("0.0.0.0", PORT);

    return 0;
}